package com.liuya.safe.entitle.handler;

import java.io.Serializable;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import com.liuya.common.exception.EntityExistException;
import com.liuya.safe.entitle.service.EntitleManagerService;
import com.liuya.safe.model.SafePrivilege;
import com.liuya.safe.model.SafeQuery;
import com.liuya.safe.model.SafeQueryEntitlement;
import com.liuya.safe.model.SafeUser;
import com.liuya.safe.policy.service.QueryManagerService;
import com.liuya.safe.util.AuthUtil;
import com.liuya.safe.util.Factory;
import org.exolab.castor.xml.MarshalException;
import org.exolab.castor.xml.ValidationException;

import com.liuya.db.sql.xml.DefineVariable;
import com.liuya.db.sql.xml.UserCategory;
import com.liuya.db.sql.xml.UserCategoryType;

import com.liuya.entitle.QueryEntitlementTestResult;

//@Component("queryEntitlementHandler")
public class QueryEntitlementHandler implements Serializable {
    private static final long serialVersionUID = 2852267318695777395L;
    private SafePrivilege privilege;
    private List queryEntitlements = new ArrayList();
//    @Autowired
//    @Qualifier("queryManagerService")
//    private QueryManagerService queryManager;
//    @Autowired
//    @Qualifier("entitleManagerService")
//    private EntitleManagerService entitleManager;

    public QueryEntitlementHandler() {
    }

    public QueryEntitlementHandler(SafePrivilege privilege, Collection entitlements) {
        this.privilege = privilege;
        this.queryEntitlements.addAll(entitlements);
    }

//    public QueryEntitlementHandler(SafePrivilege privilege, Collection entitlements, QueryManagerService queryManager, EntitleManagerService entitleManager) {
//        this.privilege = privilege;
//        this.queryEntitlements.addAll(entitlements);
//        this.queryManager = queryManager;
//        this.entitleManager = entitleManager;
//    }

    public void setPrivilege(SafePrivilege privilege) {
        this.privilege = privilege;
    }

    public SafePrivilege getPrivilege() {
        return privilege;
    }

    public List getQueryEntitlements() {
        return queryEntitlements;
    }

    public void addEntitle(SafeQueryEntitlement entitle) {
        queryEntitlements.add(entitle);
    }

    public void updateEntitle(int index, SafeQueryEntitlement entitle) {
        queryEntitlements.set(index, entitle);
    }

    public void moveEntitle(int index, String direct) {
        int moveIndex = index;

        // change column with it
        int changeIndex = -1;
        if ("top".equals(direct)) {
            if (moveIndex != 0) {
                changeIndex = 0;
            }
        } else if ("up".equals(direct)) {
            if (moveIndex != 0) {
                changeIndex = moveIndex - 1;
            }
        } else if ("down".equals(direct)) {
            if (moveIndex != (queryEntitlements.size() - 1)) {
                changeIndex = moveIndex + 1;
            }
        } else if ("bottom".equals(direct)) {
            if (moveIndex != (queryEntitlements.size() - 1)) {
                changeIndex = queryEntitlements.size() - 1;
            }
        }

        if (changeIndex != -1) {
            Object moveOne = queryEntitlements.get(moveIndex);

            if ("top".equals(direct)) {
                queryEntitlements.remove(moveIndex);
                queryEntitlements.add(0, moveOne);
            } else if ("bottom".equals(direct)) {
                queryEntitlements.remove(moveIndex);
                queryEntitlements.add(queryEntitlements.size(), moveOne);
            } else if ("up".equals(direct) || "down".equals(direct)) {
                Object changeOne = queryEntitlements.get(changeIndex);

                queryEntitlements.set(changeIndex, moveOne);
                queryEntitlements.set(moveIndex, changeOne);
            }
        }
    }

    public void deleteEntitle(int index) {
        queryEntitlements.remove(index);
    }

    public void save() throws EntityExistException {
        EntitleManagerService entitleManager = Factory.getEntitleManager("");

        Collection oldEntitles = entitleManager.getQueryEntitlements(privilege.getId());

        // delete old entries
        for (Iterator iter = oldEntitles.iterator(); iter.hasNext();) {
            SafeQueryEntitlement entitle = (SafeQueryEntitlement) iter.next();
            entitleManager.deleteQueryEntitlement(entitle.getId());
        }

        // add new entries
        for (Iterator iter = queryEntitlements.iterator(); iter.hasNext();) {
            SafeQueryEntitlement entitle = (SafeQueryEntitlement) iter.next();
            entitleManager.addQueryEntitlement(entitle);
        }
    }

    public String[] getTestContextFields() throws MarshalException, ValidationException {
        Set fields = new HashSet();

        for (Iterator iter = queryEntitlements.iterator(); iter.hasNext();) {
            SafeQueryEntitlement entitle = (SafeQueryEntitlement) iter.next();
            SafeQuery query = entitle.getQuery();

            com.liuya.db.sql.Query sqlQuery = query.getSqlQuery();
            AuthUtil.extractContextValueFields(sqlQuery, fields);

            String xmlContent = entitle.getUserCategory().getXmlContent();
            UserCategoryType unmarshal = UserCategory.unmarshal(new StringReader(xmlContent));
            DefineVariable[] variables = unmarshal.getDefineVariable();

            QueryManagerService queryManager = Factory.getQueryManager("");
            AuthUtil.extractContextValueFields(variables, queryManager, fields);
        }

        return (String[]) fields.toArray(new String[0]);
    }

    public QueryEntitlementTestResult run(Locale locale, SafeUser testUser, Map testCtx, int first, int max) {
        EntitleManagerService entitleManager = Factory.getEntitleManager("");
        QueryEntitlementTestResult testQueryEntitlement = entitleManager.testQueryEntitlement(locale, privilege.getId(), queryEntitlements, testUser, testCtx, first, max);
        return testQueryEntitlement;
    }

}
